using System;
using System.Collections.Generic;
using System.Text;
using LngT.Interfaces;
using LngT.Interfaces.DBUserRoles;
using System.Collections.ObjectModel;

namespace LngT.Core
    {
    [Serializable]
    class Database: IDatabase
        {

        #region multiton 
        private static Dictionary<string, IDatabase> _databases = new Dictionary<string,IDatabase>();

        public static IDatabase GetDatabase( string name )
            {
            return _databases[ name ];
            }

        public static IDatabase AddDatabase( string name, DBUser defaultUser )
            {
            lock( _databases )
                {
                if( _databases.ContainsKey( name ) )
                    throw new ArgumentException( "name" );
                IDatabase db = new Database( name, defaultUser );
                _databases.Add( name, db );
                return db;
                }
            }

        public static bool RemoveDatabase( string name )
            {
            return _databases.Remove( name );
            }

        public static List<string> GetDatabaseList()
            {
            List<string> result = new List<string>();
            foreach( KeyValuePair<string,IDatabase> db in _databases )
                result.Add( db.Key );

            return result;
            }

#endregion

        private Dictionary<int, IItem> _items = new Dictionary<int, IItem>();
        private List<DBUser> _users = new List<DBUser>();
        private List<ItemResult> _results = new List<ItemResult>();
        private int _itemCounter = 0;
        private int _userCounter = 0;

        private Database( string name, DBUser defaultUser )
            {
            if( defaultUser == null )
                throw new ArgumentNullException( "defaultUser" );
            _name = name;
            _users.Add( defaultUser );
            }

        public int AddItem( IItem item )
            {
            lock( this )
                {
                if( item != null )
                    _items.Add( _itemCounter++, item );
                else
                    throw new ArgumentNullException();
                return _itemCounter - 1;
                }
            }

        public bool RemoveItem( int itemID )
            {
            lock( this )
                {
                return _items.Remove( itemID );
                }
            }

        private string _name;
        public string Name
            {
            get
                {
                return _name;
                }
            set
                {
                _name = value;
                }
            }

        public bool UpdateItem( int itemId, IItem newItem )
            {
            lock( this )
                {
                if( !_items.ContainsKey( itemId ) )
                    return false;
                else
                    {
                    _items[ itemId ] = newItem;
                    return true;
                    }
                }
            }

        public IItem GetItem( int itemId )
            {
            lock( this )
                {
                return _items[ itemId ];
                }
            }

        public void AddDBUser( string userName, string password, IDBUserRole privileges )
            {
            lock( this )
                {
                if( userName == null || userName == "" )
                    throw new ArgumentException( "userName" );
                if( password == null || password == "" )
                    throw new ArgumentException( "password" );
                if( privileges == null )
                    throw new ArgumentNullException( "privileges" );
                foreach( DBUser usr in _users )
                    if( usr.UserName == userName )
                        throw new ArgumentException( "This user name already exists!" );

                _users.Add( new DBUser( _userCounter++, userName, password, privileges ));
                }
            }

        public bool RemoveDBUser( string userName )
            {
            DBUser toRemove = null;
            lock( this )
                {
                foreach( DBUser usr in _users )
                    if( usr.UserName == userName )
                        toRemove = usr;
                if( toRemove != null )
                    {
                    _users.Remove( toRemove );
                    return true;
                    }
                return false;
                }
            }

        public IDBUserRole GetDBUserPrivileges( string userName, string password )
            {
            lock( this )
                {
                foreach( DBUser usr in _users )
                    if( usr.UserName == userName && usr.Password == password)
                        return usr.Privileges;
                return null;
                }
            }

        public bool SetDBUserPrivileges( string userName, IDBUserRole privileges )
            {
            lock( this )
                {
                foreach( DBUser usr in _users )
                    if( usr.UserName == userName )
                        {
                        usr.Privileges = privileges;
                        return true;
                        }
                return false;
                }
            }

        public IEnumerable<IItem> GetItemIterator( IIterationAlgorithm algorithm )
            {
            ICollection<IItem> col = null;
            algorithm.SetItemEnumerator( _items.Values );
            algorithm.SetItemResultEnumerator( _results );
            return algorithm.GetEnumerator();
            }

        public void AddItemResult( ItemResult result )
            {
            lock( this )
                {
                _results.Add( result );
                }
            }

        public int GetUserID( string userName, string password )
            {
            foreach( DBUser usr in _users )
                if( usr.UserName == userName && usr.Password == password )
                    return usr.ID;
            throw new Exception( "User not found!" );
            }
        }
    }
